package cn.rengy.tpa.wxmp.profitsharing;

import java.util.Map;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.w3c.dom.Document;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.XmlUtil;
import cn.rengy.lang.DataConverter;
import cn.rengy.lang.ResultEntity;
import cn.rengy.tool.http.HttpUtils;
import cn.rengy.tpa.wxmp.pay.PayCode;
import cn.rengy.tpa.wxmp.util.WXPayConstants.SignType;
import cn.rengy.tpa.wxmp.util.WeChatUtil;
import cn.rengy.tpa.wxmp.util.WxRequest;
/**
 * 分账
 * https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_1&index=1
 * @author rengy
 *
 */
public class ProfitSharingApi {
	private static Logger logger = LoggerFactory.getLogger(ProfitSharingApi.class);
	private static final String profitsharing="https://api.mch.weixin.qq.com/secapi/pay/profitsharing";
	private static final String addreceiver="https://api.mch.weixin.qq.com/pay/profitsharingaddreceiver";
	
	private static final String finish= "https://api.mch.weixin.qq.com/secapi/pay/profitsharingfinish";
	/**
	 * 添加分账接收方
	 * @throws Exception 
	 */
	public static ResultEntity<?> addReceiver(DataConverter dataConverter,String mchKey,AddReceiverDTO AddReceiverDTO){
		String receiver=null;
		try {
			receiver = dataConverter.beanToJson(AddReceiverDTO.getReceiver());
		} catch (Exception e) {
			logger.error(ExceptionUtil.stacktraceToString(e,10000));
			return ResultEntity.fail("ERROR","beanToXml解析时出错");
		}
		String nonce_str=RandomStringUtils.randomNumeric(32);
		//String post=XmlUtil.mapToXmlStr(data, "xml");
		AddReceiverRO addReceiverRO=new AddReceiverRO();
		addReceiverRO.setAppid(AddReceiverDTO.getAppid());
		addReceiverRO.setMch_id(AddReceiverDTO.getMch_id());
		addReceiverRO.setNonce_str(nonce_str);
		addReceiverRO.setReceiver(receiver);
		String sign=WeChatUtil.signatureBean(SignType.HMAC_SHA256, mchKey, addReceiverRO);
		addReceiverRO.setSign(sign);
		String post=null;
		try {
			post = dataConverter.beanToXml(addReceiverRO);
		} catch (Exception e) {
			logger.error(ExceptionUtil.stacktraceToString(e,10000));
			return ResultEntity.fail("ERROR","beanToXml解析时出错");
		}
		logger.info("添加分账接收方request:{}",post);
		String result=HttpUtils.httpPost(addreceiver,MediaType.APPLICATION_XML_VALUE, post);
		logger.info("添加分账接收方response:{}",result);
		
		Document document = XmlUtil.parseXml(result);
    	Map<String,Object> resultMap=XmlUtil.xmlToMap(document.getDocumentElement());
        
        String return_code= MapUtils.getString(resultMap, "return_code");
        if (PayCode.FAIL.toString().equals(return_code)){
        	String return_msg=MapUtils.getString(resultMap,"return_msg");
        	logger.error("返回状态码异常,return_msg:{}", return_msg);
        	//throw new PayApiException(PayCode.FAIL, .toString());
        	return ResultEntity.fail(return_msg);
        }
        String result_code=MapUtils.getString(resultMap,"result_code");
        if (PayCode.FAIL.toString().equals(result_code)) {
    		String err_code=MapUtils.getString(resultMap,"err_code");
        	String err_code_des=MapUtils.getString(resultMap,"err_code_des");
        	logger.error("添加分账接收方，code:{},mes:{}",err_code,err_code_des);
        	return ResultEntity.fail(err_code,err_code_des);
        }
        WeChatUtil.validResponseSign(SignType.HMAC_SHA256, mchKey, resultMap);
		
		return ResultEntity.ok();
	}
	/**
	 * 请求多次分账
	 */
	public void multiProfitSharing() {
		
	}
	/**
	 * 完结分账
	 * @param dataConverter
	 * @param mchKey
	 * @param profitSharingfinishDTO
	 * @param cert
	 * @return
	 */
	public static ResultEntity<String> finish(DataConverter dataConverter,String mchKey,ProfitSharingfinishDTO profitSharingfinishDTO,byte []cert) {
		ProfitSharingfinishRO profitSharingfinishRO=new ProfitSharingfinishRO();
		profitSharingfinishRO.setAppid(profitSharingfinishDTO.getAppid());
		profitSharingfinishRO.setDescription(profitSharingfinishDTO.getDescription());
		profitSharingfinishRO.setMch_id(profitSharingfinishDTO.getMch_id());
		String nonce_str=RandomStringUtils.randomAlphanumeric(32);
		profitSharingfinishRO.setNonce_str(nonce_str);
		profitSharingfinishRO.setOut_order_no(profitSharingfinishDTO.getOut_order_no());
		profitSharingfinishRO.setTransaction_id(profitSharingfinishDTO.getTransaction_id());
		String sign=WeChatUtil.signatureBean(SignType.HMAC_SHA256, mchKey, profitSharingfinishRO);
		profitSharingfinishRO.setSign(sign);
		String post;
		try {
			post = dataConverter.beanToXml(profitSharingfinishRO);
		} catch (Exception e) {
			logger.error(ExceptionUtil.stacktraceToString(e,10000));
			return ResultEntity.fail("ERROR","beanToXml解析时出错");
		}
		logger.info("请求分账完结request:{}",post);
		String result;
		try {
			result=WxRequest.postSSL(finish, post, cert, profitSharingfinishDTO.getMch_id());
			//result = postSSL2(profitsharing, post, cert, profitSharingfinishDTO.getMch_id());
		} catch ( Exception e) {
			logger.error(ExceptionUtil.stacktraceToString(e,10000));
			return ResultEntity.fail("ERROR","请求微信服务器时出错");
		}
		logger.info("请求分账完结response:{}",result);
		Document document = XmlUtil.parseXml(result);
    	Map<String,Object> resultMap=XmlUtil.xmlToMap(document.getDocumentElement());
        
        String return_code= MapUtils.getString(resultMap, "return_code");
        if (PayCode.FAIL.toString().equals(return_code)){
        	String return_msg=MapUtils.getString(resultMap,"return_msg");
        	logger.error("返回状态码异常,return_msg:{}", return_msg);
        	//throw new PayApiException(PayCode.FAIL, .toString());
        	return ResultEntity.fail(return_msg);
        }
        String result_code=MapUtils.getString(resultMap,"result_code");
        if (PayCode.FAIL.toString().equals(result_code)) {
    		String err_code=MapUtils.getString(resultMap,"err_code");
        	String err_code_des=MapUtils.getString(resultMap,"err_code_des");
        	logger.error("分账失败，code:{},mes:{}",err_code,err_code_des);
        	return ResultEntity.fail(err_code,err_code_des);
        }
        WeChatUtil.validResponseSign(SignType.HMAC_SHA256, mchKey, resultMap);
        String order_id =MapUtils.getString(resultMap, "order_id");//微信分账单号

		return ResultEntity.ok(order_id);
	}
	/**
	 * 请求单次分账
	 * @throws Exception 
	 */
	public static ResultEntity<String> profitSharing(DataConverter dataConverter,String mchKey,ProfitSharingDTO profitSharingDTO,byte []cert) {
		String receivers;
		try {
			receivers = dataConverter.beanToJson(profitSharingDTO.getReceivers());
		} catch (Exception e) {
			logger.error(ExceptionUtil.stacktraceToString(e,10000));
			return ResultEntity.fail("ERROR","beanToJson解析时出错");
		}
		String nonce_str=RandomStringUtils.randomAlphanumeric(32);
		ProfitSharingRO profitSharingRO=new ProfitSharingRO();
		profitSharingRO.setAppid(profitSharingDTO.getAppid());
		profitSharingRO.setMch_id(profitSharingDTO.getMch_id());
		profitSharingRO.setNonce_str(nonce_str);
		profitSharingRO.setReceivers(receivers);
		profitSharingRO.setOut_order_no(profitSharingDTO.getOut_order_no());
		profitSharingRO.setTransaction_id(profitSharingDTO.getTransaction_id());
		String sign=WeChatUtil.signatureBean(SignType.HMAC_SHA256, mchKey, profitSharingRO);
		profitSharingRO.setSign(sign);
		String post;
		try {
			post = dataConverter.beanToXml(profitSharingRO);
		} catch (Exception e) {
			logger.error(ExceptionUtil.stacktraceToString(e,10000));
			return ResultEntity.fail("ERROR","beanToXml解析时出错");
		}
		logger.info("请求单次分账request:{}",post);
		String result;
		try {
			result = WxRequest.postSSL(profitsharing, post, cert, profitSharingDTO.getMch_id());
		} catch ( Exception e) {
			logger.error(ExceptionUtil.stacktraceToString(e,10000));
			return ResultEntity.fail("ERROR","请求微信服务器时出错");
		}
		logger.info("请求单次分账response:{}",result);
		
		Document document = XmlUtil.parseXml(result);
    	Map<String,Object> resultMap=XmlUtil.xmlToMap(document.getDocumentElement());
        
        String return_code= MapUtils.getString(resultMap, "return_code");
        if (PayCode.FAIL.toString().equals(return_code)){
        	String return_msg=MapUtils.getString(resultMap,"return_msg");
        	logger.error("返回状态码异常,return_msg:{}", return_msg);
        	//throw new PayApiException(PayCode.FAIL, .toString());
        	return ResultEntity.fail(return_msg);
        }
        String result_code=MapUtils.getString(resultMap,"result_code");
        if (PayCode.FAIL.toString().equals(result_code)) {
    		String err_code=MapUtils.getString(resultMap,"err_code");
        	String err_code_des=MapUtils.getString(resultMap,"err_code_des");
        	logger.error("分账失败，code:{},mes:{}",err_code,err_code_des);
        	return ResultEntity.fail(err_code,err_code_des);
        }
        WeChatUtil.validResponseSign(SignType.HMAC_SHA256, mchKey, resultMap);
        String order_id =MapUtils.getString(resultMap, "order_id");//微信分账单号

		return ResultEntity.ok(order_id);
	}
	/**
	 * 删除分账接收方
	 */
	public void removeReceiver() {
		
	}
	
	
	/**
	 * 查询分账结果
	 * 发起分账请求后，可调用此接口查询分账结果；
	 * 发起分账完结请求后，可调用此接口查询分账完结的执行结果。 
	 */
	public void profitSharingQuery() {
		
	}
	 

	
	/**
	 * 完结分账
	 * 1、不需要进行分账的订单，可直接调用本接口将订单的金额全部解冻给本商户 
	2、调用多次分账接口后，需要解冻剩余资金时，调用本接口将剩余的分账金额全部解冻给特约商户 
	3、已调用请求单次分账后，剩余待分账金额为零，不需要再调用此接口。
	 */
	public void profitSharingFinish() {
		
	}
	/**
	 * 分账回退
	 * 对订单进行退款时，如果订单已经分账，可以先调用此接口将指定的金额从分账接收方（仅限商户类型的分账接收方）回退给本商户，然后再退款。 

 回退以原分账请求为依据，可以对分给分账接收方的金额进行多次回退，只要满足累计回退不超过该请求中分给接收方的金额。 

此接口采用同步处理模式，即在接收到商户请求后，会实时返回处理结果

此功能需要接收方在商户平台-交易中心-分账-分账接收设置下，开启同意分账回退后，才能使用。

	 */
	public void profitSharingReturn() {
		
	}
	
	
	/**
	 * 回退结果查询
	 * 商户需要核实回退结果，可调用此接口查询回退结果。

如果分账回退接口返回状态为处理中，可调用此接口查询回退结果 

	 */
	public void profitSharingReturnQuery() {
		
	}
}
